#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# QcmDoubleEdit Copyright (C) 2009  Chris Marsh
# Version 0.2.0
#
# Currency Converter is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or any later version.
#
# This program is distributed in the hope that it will be useful, 
# but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# ********************************************************************
# QcmDoubleEdit.py contains 3 classes:
#
#       QcmAbstractDoubleEdit
#           Base class for the editors
#
#       QcmDoubleEdit
#           Inherits QcmAbstractDoubleEdit and provides a popup
#           number pad editor.
#
#       QcmCalculatorEdit
#           Inherits QcmAbstractDoubleEdit and provides a popup
#           calculator editor.
# ********************************************************************

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from QcmNumberPad import QcmNumberPad
from QcmCalculator import QcmCalculator
import QcmDoubleEdit_rc

# ********************************************************************

class QcmAbstractDoubleEdit(QLineEdit):
        
    def __init__(self, parent = None):
        super(QcmAbstractDoubleEdit, self).__init__(parent)
        
        self.setObjectName("QcmDoubleEdit")
        self.setDecimals(0)
        self.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.setMaxLength(15)
        self.popup = None
        self.popupButton = QToolButton(self)
        self.popupButton.setObjectName("popupButton")
        pixmap=QPixmap(":/calc.png")
        self.popupButton.setIcon(QIcon(pixmap))
        self.popupButton.setIconSize(pixmap.size())
        self.popupButton.setCursor(Qt.ArrowCursor)
        self.popupButton.setStyleSheet("QToolButton#popupButton {border: none; padding-top: 2px; padding-bottom: 2px; padding-right: 4px;}")
        self.popupButton.setFocusPolicy(Qt.NoFocus)
        
        self.prefixLabel = QLabel("",  self)
        self.prefixLabel.setAlignment(Qt.AlignRight)
        self.suffixLabel = QLabel("",  self)
        self.suffixLabel.setAlignment(Qt.AlignLeft)
        
        frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
        msz = self.minimumSizeHint()
        self.setMinimumSize(
                max(msz.width(),
                    self.popupButton.sizeHint().width() + self.prefixLabel.sizeHint().width() + frameWidth * 2 + 2),
                max(msz.height(),
                    self.popupButton.sizeHint().height() + frameWidth * 2 + 2))
        
        self.connect(self, SIGNAL("textChanged(const QString&)"),  self.valueChanged)
        self.connect(self,  SIGNAL("editingFinished()"),  self.fixup)
        self.connect(self ,SIGNAL("showPopup()"), self.showPopup)
        self.connect(self.popupButton,SIGNAL("clicked()"), self.showPopup)
    # __init__
    
    def setDecimals(self,  decimals):
        self.__decimals = decimals
        validator = QDoubleValidator(-9999999.0, 9999999.0, self.__decimals,  self)
        self.setValidator(validator)
    
    def resizeEvent(self,  evt):
        buttonSize = self.popupButton.sizeHint()
        frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
        buttonX = self.rect().right() - frameWidth - buttonSize.width()
        buttonY = (self.rect().bottom() + 1 - buttonSize.height())/2
        self.popupButton.move(buttonX, buttonY)
        
        suffixSize = self.suffixLabel.sizeHint()
        suffixX = buttonX - suffixSize.width() 
        suffixY = (self.rect().bottom() - suffixSize.height())/2 +1
        self.suffixLabel.move(suffixX,  suffixY)
        prefixSize = self.prefixLabel.sizeHint()
        prefixY = (self.rect().bottom() - prefixSize.height())/2 +1
        self.prefixLabel.move(0,  prefixY)
        self.setStyleSheet("QLineEdit#QcmDoubleEdit {padding-right: %spx;}" % 
                           (self.popupButton.sizeHint().width() + self.suffixLabel.sizeHint().width() + frameWidth))
    # resizeEvent

    def keyPressEvent(self, event):
        popupTriggers = (Qt.Key_Up, Qt.Key_Down, Qt.Key_Enter, Qt.Key_Return)
        if event.key() in popupTriggers:
            self.emit(SIGNAL("showPopup()"),  ())
        else:
            return QLineEdit.keyPressEvent(self, event)
    # keyPressEvent
    
    def fixup(self):
        template = "%%.%df" % self.__decimals
        self.setText(template % self.value)
    #fixup
    
    def prefix(self):
        return self.prefixLabel.text()
    # prefix
    
    @pyqtSignature("setprefix(QString)")
    def setPrefix(self,  prefixText):
        self.prefixLabel.setText(prefixText)
    # setPrefix
    
    prefix = pyqtProperty("QString",  prefix,  setPrefix)
    
    def suffix(self):
        return self.suffixLabel.text()
    # suffix
    
    @pyqtSignature("setsuffix(QString)")
    def setSuffix(self,  suffixText):
        self.prefixLabel.setText(suffixText)
    # setSuffix
    
    suffix = pyqtProperty("QString",  suffix,  setSuffix)
    
    def value(self):
        return self.text().toDouble()[0]
    # value
    
    @pyqtSignature("setValue(double)")
    def setValue(self,  newValue):
        template = "%%.%df" % self.__decimals
        self.setText(template % newValue)
    # setValue
    
    value = pyqtProperty("double", value, setValue)
    
    def valueChanged(self):
        self.emit(SIGNAL("valueChanged(double)"),  (self.value))
    # valueChanged
    
    def createPopup(self):
        self.popup = QWidget(self)
    # createPopup
    
    def updateDisplay(self,  text):
        self.setText(text)
        self.fixup()
    # updateDisplay

    def showPopup(self):
        self.selectAll()
        coord = QPoint(self.geometry().x(),  self.geometry().y())
        if not self.parent() == None:
            coord = self.parent().mapToGlobal(coord)
        self.createPopup()
        #TODO: Replace current hack of rendering off screen to allow the size to be calculated
        self.popup.setGeometry(-10000,  -10000,  0, 0)
        self.popup.show()
        coord.setX(coord.x()+self.width()-self.popup.width())
        coord.setY(coord.y()+self.height())
        self.popup.setGeometry(coord.x(),  coord.y(),  0, 0)
    # showPopup

# ********************************************************************

class QcmDoubleEdit(QcmAbstractDoubleEdit):
        
    def __init__(self, decimals=2,  parent = None):
        super(QcmDoubleEdit, self).__init__(parent)
        self.setDecimals(decimals)
    # __init__
    
    def createPopup(self):
        self.popup= QcmNumberPad(self)
        self.popup.setDeleteOnClose(True)
        self.connect(self.popup, SIGNAL("keyClicked(QString&)"),  self.digitClicked)
        self.connect(self.popup, SIGNAL("backspaceClicked()"), self.backspace)
        self.connect(self.popup,  SIGNAL("enterClicked()"),  self.fixup)
        self.connect(self.popup, SIGNAL("clearClicked()"), self.clear)
    # createNumberPad
    
    def updateDisplay(self,  text):
        self.setText(text)
        self.fixup()
    # updateDisplay

    def digitClicked(self,  padInput):
        if self.value == 0:
            self.setText("")
        self.insert(padInput)
    #digitClicked
    
    def clear(self):
        self.setValue(0.00)
    # clear

# ********************************************************************

class QcmCalculatorEdit(QcmAbstractDoubleEdit):
        
    def __init__(self, decimals=2,  parent = None):
        super(QcmCalculatorEdit, self).__init__(parent)
        self.setDecimals(decimals)
    # __init_
    
    def createPopup(self):
        self.popup= QcmCalculator(self)
        self.popup.setDeleteOnClose(True)
        self.popup.display.setText(self.text())
        self.connect(self.popup, SIGNAL("finishedCalculating(QString&)"),  self.updateDisplay)
    # createNumberPad
    
    def updateDisplay(self,  text):
        self.setText(text)
        self.fixup()
    # updateDisplay

# ********************************************************************

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    form =QcmDoubleEdit()
    form.show()
    sys.exit(app.exec_())
